home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / dev / gui / FoxGuiSource.lha / FoxLibSource / BoolGads.c next >
C/C++ Source or Header  |  2001-07-07  |  24KB  |  780 lines

  1. /* FoxGUI - The fast, flexible, free Amiga GUI system
  2.     Copyright (C) 2001 Simon Fox (Foxysoft)
  3.  
  4. This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  5. Foxysoft: www.foxysoft.co.uk      Email:simon@foxysoft.co.uk                */
  6.  
  7. /******************************************************************************
  8.  * Shared library code.  Cannot call functions which use exit() such as:
  9.  * printf(), fprintf()
  10.  *
  11.  * Otherwise:
  12.  * The linker returns "__XCEXIT undefined" and the program will fail.
  13.  * This is because you must not exit() a library!
  14.  *
  15.  * Also:
  16.  * proto/exec.h must be included instead of clib/exec_protos.h and
  17.  * __USE_SYSBASE must be defined.
  18.  *
  19.  * Otherwise:
  20.  * The linker returns "Absolute reference to symbol _SysBase" and the
  21.  * library crashes.  Presumably the same is true for the other protos.
  22.  ******************************************************************************/
  23.  
  24. #define __USE_SYSBASE
  25.  
  26. #include <proto/mathieeedoubbas.h>
  27. #include <string.h>
  28.  
  29. #include <proto/intuition.h>
  30. #include <proto/graphics.h>
  31. #include "/FoxInclude/foxgui.h"
  32. #include "FoxGuiTools.h"
  33.  
  34. #define RBWIN(r)    ((struct Window *) r->RBGad.UserData)
  35. #define TBWIN(t)    ((struct Window *) t->TickBoxGad.UserData)
  36.  
  37. void EnableRadioButton(RadioButton *rb)
  38.    {
  39.    Diagnostic("EnableRadioButton", ENTER, TRUE);
  40.     if (rb && !rb->Active)
  41.         {
  42.         struct Window *wptr = (struct Window *) rb->RBGad.UserData;
  43.  
  44.         /*    If the button is clear, only the border will be refreshed, leaving the rest of the button
  45.             still looking shaded and disabled.  Clear it here before refreshing. */
  46.         if (rb->hidden == 0)
  47.             {
  48.             AreaBlank(wptr->RPort, rb->RBGad.LeftEdge, rb->RBGad.TopEdge, rb->RBGad.Width, rb->RBGad.Height);
  49.             EnableGadget(&rb->RBGad, wptr, TRUE);
  50.             DrawRBCentre(rb);
  51.             }
  52.         else // Radiobutton is hidden.
  53.             rb->RBGad.Flags ^= GFLG_DISABLED;
  54.         rb->Active = TRUE;
  55.         Diagnostic("EnableRadioButton", EXIT, TRUE);
  56.         }
  57.     else
  58.         Diagnostic("EnableRadioButton", EXIT, FALSE);
  59.    }
  60.  
  61. void DisableRadioButton(RadioButton *rb)
  62.    {
  63.    Diagnostic("DisableRadioButton", ENTER, TRUE);
  64.     if (rb && rb->Active)
  65.         {
  66.         struct Window *wptr = (struct Window *) rb->RBGad.UserData;
  67.  
  68.         if (rb->hidden == 0)
  69.             DisableGadget(&rb->RBGad, wptr, TRUE);
  70.         else // Radiobutton is hidden.
  71.             rb->RBGad.Flags |= GFLG_DISABLED;
  72.         rb->Active = FALSE;
  73.         Diagnostic("DisableRadioButton", EXIT, TRUE);
  74.         }
  75.     else
  76.         Diagnostic("DisableRadioButton", EXIT, FALSE);
  77.    }
  78.  
  79. void EnableTickBox(TickBox *tb)
  80.    {
  81.    Diagnostic("EnableTickBox", ENTER, TRUE);
  82.     if (tb && !tb->Active)
  83.         {
  84.         struct Window *wptr = (struct Window *) tb->TickBoxGad.UserData;
  85.  
  86.         if (tb->hidden == 0)
  87.             {
  88.             /* Only the border will be refreshed, leaving the rest of the tick box still looking shaded and
  89.                 disabled.  Clear it here before refreshing. */
  90.             AreaColFill(wptr->RPort, tb->TickBoxGad.LeftEdge, tb->TickBoxGad.TopEdge, tb->TickBoxGad.Width,
  91.                     tb->TickBoxGad.Height, tb->WidgetData->flags & BG_CLEAR ? wptr->RPort->BgPen : tb->nsTick.FrontPen);
  92.             EnableGadget(&(tb->TickBoxGad), wptr, TRUE);
  93.             }
  94.         else
  95.             tb->TickBoxGad.Flags ^= GFLG_DISABLED;
  96.         tb->Active = TRUE;
  97.         Diagnostic("EnableTickBox", EXIT, TRUE);
  98.         }
  99.     else
  100.         Diagnostic("EnableTickBox", EXIT, FALSE);
  101.    }
  102.  
  103. void DisableTickBox(TickBox *tb)
  104.    {
  105.    Diagnostic("DisableTickBox", ENTER, TRUE);
  106.     if (tb && tb->Active)
  107.         {
  108.         struct Window *wptr = (struct Window *) tb->TickBoxGad.UserData;
  109.  
  110.         if (tb->hidden == 0)
  111.             DisableGadget(&tb->TickBoxGad, wptr, TRUE);
  112.         else // Tickbox is hidden
  113.             tb->TickBoxGad.Flags |= GFLG_DISABLED;
  114.         tb->Active = FALSE;
  115.         Diagnostic("DisableTickBox", EXIT, TRUE);
  116.         }
  117.     else
  118.         Diagnostic("DisableTickBox", EXIT, FALSE);
  119.    }
  120.  
  121. BOOL FOXLIB SetTickBoxValue(REGA0 TickBox *tb, REGD0 BOOL value)
  122.     {
  123.     UWORD GadPos = RemoveGList((struct Window *) tb->TickBoxGad.UserData, &tb->TickBoxGad, 1L);
  124.     if (GadPos != -1)
  125.         {
  126.         tb->Ticked = value;
  127.         tb->TickBoxGad.GadgetRender = (APTR) (tb->Ticked ? &tb->sTick : &tb->nsTick);
  128.         AddGList((struct Window *) tb->TickBoxGad.UserData, &tb->TickBoxGad, (unsigned long)
  129.                 GadPos, 1L, NULL);
  130.         RefreshGList(&tb->TickBoxGad, (struct Window *) tb->TickBoxGad.UserData, NULL, 1);
  131.         return TRUE;
  132.         }
  133.     return FALSE;
  134.     }
  135.  
  136. BOOL FOXLIB TickBoxValue(REGA0 TickBox *tb)
  137.     {
  138.     Diagnostic("TickBoxValue", ENTER, TRUE);
  139.     if (tb)
  140.         {
  141.         Diagnostic("TickBoxValue", EXIT, TRUE);
  142.         return tb->Ticked;
  143.         }
  144.     return Diagnostic("TickBoxValue", EXIT, FALSE);
  145.     }
  146.  
  147. BOOL ShowTickBox(TickBox *tb)
  148.     {
  149.     Diagnostic("ShowTickBox", ENTER, TRUE);
  150.     if (tb)
  151.         {
  152.         BOOL InFrame = !ISGUIWINDOW(tb->WidgetData->Parent);
  153.  
  154.         if (tb->hidden == 1) // The tick box is really hidden
  155.             if (InFrame && ((Frame *) tb->WidgetData->Parent)->hidden != 0) // The tick box is in a hidden frame so it remains hidden
  156.                 tb->hidden = -1;
  157.             else
  158.                 {
  159.                 struct Window *w = (struct Window *) tb->TickBoxGad.UserData;
  160.  
  161.                 AddGadget(w, &tb->TickBoxGad, -1);
  162.                 if (!(tb->WidgetData->flags & BG_CLEAR))
  163.                     AreaColFill(w->RPort, tb->TickBoxGad.LeftEdge, tb->TickBoxGad.TopEdge, tb->TickBoxGad.Width,
  164.                             tb->TickBoxGad.Height, tb->nsTick.FrontPen);
  165.                 RefreshGList(&tb->TickBoxGad, w, NULL, 1);
  166.                 tb->hidden = 0;
  167.                 }
  168.         return Diagnostic("ShowTickBox", EXIT, TRUE);
  169.         }
  170.     return Diagnostic("ShowTickBox", EXIT, FALSE);
  171.     }
  172.  
  173. BOOL HideTickBox(TickBox *tb)
  174.     {
  175.     Diagnostic("HideTickBox", ENTER, TRUE);
  176.     if (tb)
  177.         {
  178.         if (tb->hidden == 0)
  179.             {
  180.             BYTE BackCol = GetBackCol(tb->WidgetData->Parent);
  181.             struct Window *w = (struct Window *) tb->TickBoxGad.UserData;
  182.  
  183.             RemoveGadget(w, &(tb->TickBoxGad));
  184.             AreaColFill(w->RPort, tb->TickBoxGad.LeftEdge, tb->TickBoxGad.TopEdge, tb->TickBoxGad.Width,
  185.                     tb->TickBoxGad.Height, BackCol);
  186.             }
  187.         tb->hidden = 1;
  188.         return Diagnostic("HideTickBox", EXIT, TRUE);
  189.         }
  190.     return Diagnostic("HideTickBox", EXIT, FALSE);
  191.     }
  192.  
  193. void DestroyTickBox(TickBox *tb, BOOL refresh)
  194.     {
  195.     Frame *Child; // Couild be any object type.
  196.  
  197.     Diagnostic("DestroyTickBox", ENTER, TRUE);
  198.     if (!tb)
  199.         {
  200.         Diagnostic("DestroyTickBox", EXIT, FALSE);
  201.         return;
  202.         }
  203.     if (tb->hidden == 0)
  204.         {
  205.         if (refresh)
  206.             HideTickBox(tb);
  207.         else
  208.             RemoveGadget((struct Window *) tb->TickBoxGad.UserData, &(tb->TickBoxGad));
  209.         }
  210.     if (tb == Gui.FirstTickBox)
  211.         Gui.FirstTickBox = tb->Next;
  212.     else
  213.         {
  214.         TickBox *prev = Gui.FirstTickBox;
  215.         while (prev->Next != tb)
  216.             prev = prev->Next;
  217.         prev->Next = tb->Next;
  218.         }
  219.     if (tb->WidgetData->os)
  220.         GuiFree(tb->WidgetData->os);
  221.     Child = tb->WidgetData->ChildWidget;
  222.     while (Child)
  223.         {
  224.         void *next = Child->WidgetData->NextWidget;
  225.         Child->WidgetData->ParentControl = NULL; // Otherwise destroy will fail.
  226.         Destroy(Child, refresh);
  227.         Child = next;
  228.         }
  229.     GuiFree(tb->WidgetData);
  230.     GuiFree(tb);
  231.     Diagnostic("DestroyTickBox", EXIT, TRUE);
  232.     }
  233.  
  234. /* Given a pointer to any radio button, this function returns a pointer to the active member of the
  235.     group.  If no member of the group is active or an error occurs, NULL is returned. */
  236. RadioButton* FOXLIB ActiveRadioButton(REGA0 RadioButton *rb)
  237.     {
  238.     if (rb)
  239.         {
  240.         struct MutexList *ml = rb->MList;
  241.  
  242.         while (ml)
  243.             {
  244.             if (ml->Mutex->RBGad.Flags & GFLG_SELECTED)
  245.                 return ml->Mutex;
  246.             ml = ml->Next;
  247.             }
  248.         }
  249.     return NULL;
  250.     }
  251.  
  252. BOOL ShowRadioButton(RadioButton *rb)
  253.     {
  254.     Diagnostic("ShowRadioButton", ENTER, TRUE);
  255.     if (rb)
  256.         {
  257.         BOOL InFrame = !ISGUIWINDOW(rb->WidgetData->Parent);
  258.  
  259.         if (rb->hidden == 1) // The radio button is really hidden
  260.             if (InFrame && ((Frame *) rb->WidgetData->Parent)->hidden != 0) // The radio button is in a hidden frame so it remains hidden
  261.                 rb->hidden = -1;
  262.             else
  263.                 {
  264.                 struct Window *w = (struct Window *) rb->RBGad.UserData;
  265.  
  266.                 AddGadget(w, &rb->RBGad, -1);
  267.                 DrawRBCentre(rb);
  268.                 RefreshGList(&rb->RBGad, w, NULL, 1);
  269.                 rb->hidden = 0;
  270.                 }
  271.         return Diagnostic("ShowRadioButton", EXIT, TRUE);
  272.         }
  273.     return Diagnostic("ShowRadioButton", EXIT, FALSE);
  274.     }
  275.  
  276. BOOL HideRadioButton(RadioButton *rb)
  277.     {
  278.     Diagnostic("HideRadioButton", ENTER, TRUE);
  279.     if (rb)
  280.         {
  281.         if (rb->hidden == 0)
  282.             {
  283.             BYTE BackCol = GetBackCol(rb->WidgetData->Parent);
  284.             struct Window *w = (struct Window *) rb->RBGad.UserData;
  285.  
  286.             RemoveGadget(w, &rb->RBGad);
  287.             AreaColFill(w->RPort, rb->RBGad.LeftEdge, rb->RBGad.TopEdge, rb->RBGad.Width, rb->RBGad.Height,
  288.                     BackCol);
  289.             }
  290.         rb->hidden = 1;
  291.         return Diagnostic("HideRadioButton", EXIT, TRUE);
  292.         }
  293.     return Diagnostic("HideRadioButton", EXIT, FALSE);
  294.     }
  295.  
  296. void DestroyRadioButton(RadioButton *rb, BOOL refresh)
  297.     {
  298.     if (rb && rb->MList) // Radio buttons MUST have a mutex list even if the only member is itself.
  299.         {
  300.         Frame *Child; // Could be any type of control
  301.  
  302.         if (rb->hidden == 0) // If not hidden
  303.             {
  304.             if (refresh)
  305.                 HideRadioButton(rb);
  306.             else
  307.                 RemoveGadget((struct Window *) rb->RBGad.UserData, &(rb->RBGad));
  308.             }
  309.  
  310.         if (rb == Gui.FirstRadioButton)
  311.             Gui.FirstRadioButton = rb->Next;
  312.         else
  313.             {
  314.             RadioButton *prev = Gui.FirstRadioButton;
  315.             while (prev->Next != rb)
  316.                 prev = prev->Next;
  317.             prev->Next = rb->Next;
  318.             }
  319.  
  320.         // Sort out the mutex list (remember other radio buttons may still be using it).
  321.         if (rb->MList->Mutex == rb)
  322.             {
  323.             /*    The first item in the mutex list is ourself so we have to find every radio button using
  324.                 this mutex list and reset their mutex pointers to point to the next item. */
  325.             RadioButton *b = Gui.FirstRadioButton;
  326.             while (b)
  327.                 {
  328.                 if (b->MList == rb->MList)
  329.                     b->MList = b->MList->Next;
  330.                 b = b->Next;
  331.                 }
  332.  
  333.             /* This radio button has already been removed from the Gui list and so hasn't been affected by
  334.                 the loop above so our MList still points to the one we want to free.  It's now safe to free
  335.                 it. */
  336.             GuiFree(rb->MList);
  337.             }
  338.         else
  339.             {
  340.             /* Remove this radio button's item from the MList.  Since our item isn't the first in the
  341.                 MList, this will also remove it from the MList for all other radio buttons in the list. */
  342.             struct MutexList *ml = rb->MList, *pml = NULL;
  343.  
  344.             while (ml->Mutex != rb)
  345.                 {
  346.                 pml = ml;
  347.                 ml = ml->Next;
  348.                 }
  349.             /*    The if statement below should never fail.  Our own mutex should always be in the list and
  350.                 cannot be first because we checked for this above. */
  351.             if (ml && pml)
  352.                 {
  353.                 pml->Next = ml->Next;
  354.                 GuiFree(ml);
  355.                 }
  356.             }
  357.  
  358.         if (rb->WidgetData->os)
  359.             GuiFree(rb->WidgetData->os);
  360.         Child = rb->WidgetData->ChildWidget;
  361.         while (Child)
  362.             {
  363.             void *next = Child->WidgetData->NextWidget;
  364.             Child->WidgetData->ParentControl = NULL; // Otherwise destroy will fail.
  365.             Destroy(Child, refresh);
  366.             Child = next;
  367.             }
  368.         GuiFree(rb->WidgetData);
  369.         GuiFree(rb);
  370.         }
  371.     }
  372.  
  373. void DrawRBCentre(RadioButton *rb)
  374.     {
  375.     if (rb->RBGad.Flags & GFLG_SELECTED)
  376.         {
  377.         char APenCol = ((struct Window *) rb->RBGad.UserData)->RPort->FgPen;
  378.         register int i, j, x1, x2, y, l;
  379.  
  380.         SetAPen(((struct Window *) rb->RBGad.UserData)->RPort, rb->BLight.BackPen);
  381.         for (l = 0; l < rb->RBGad.Height - 4; l++)
  382.             {
  383.             i = 4 * l;
  384.             if (rb->RBGad.Width > 5 && (l == 0 || l == rb->RBGad.Height - 5))
  385.                 j = 1;
  386.             else
  387.                 j = 0;
  388.             x1 = 2 + j;
  389.             x2 = rb->RBGad.Width - 3 - j;
  390.             y = l + 2;
  391.             if (l == 0)
  392.                 Move(((struct Window *) rb->RBGad.UserData)->RPort, rb->RBGad.LeftEdge + x1, rb->RBGad.TopEdge + y);
  393.             else
  394.                 Draw(((struct Window *) rb->RBGad.UserData)->RPort, rb->RBGad.LeftEdge + x1, rb->RBGad.TopEdge + y);
  395.             Draw(((struct Window *) rb->RBGad.UserData)->RPort, rb->RBGad.LeftEdge + x2, rb->RBGad.TopEdge + y);
  396.             }
  397.         SetAPen(((struct Window *) rb->RBGad.UserData)->RPort, APenCol);
  398.         }
  399.     }
  400.  
  401. void ResizeRadioButton(RadioButton *rb, int x, int y, int width, int height, BOOL eraseold)
  402.     {
  403.     /*    If the radio button is in a coloured frame then no need to blank it because the parent frame will
  404.         blank it's entire contents. */
  405.     if (eraseold && GetBackCol(rb->WidgetData->Parent) == RBWIN(rb)->RPort->BgPen)
  406.         AreaBlank(((struct Window *) rb->RBGad.UserData)->RPort, rb->RBGad.LeftEdge,
  407.                 rb->RBGad.TopEdge, rb->RBGad.Width, rb->RBGad.Height);
  408.  
  409.     rb->BevelPoints[0] = rb->BevelPoints[12] = width - 3;
  410.     rb->BevelPoints[7] = rb->BevelPoints[15] = height - 3;
  411.     rb->BevelPoints[9] = height - 2;
  412.     rb->BevelPoints[11] = rb->BevelPoints[13] = height - 1;
  413.     rb->BevelPoints[14] = rb->BevelPoints[16] = width - 1;
  414.     rb->BevelPoints[18] = width - 2;
  415.  
  416.     rb->RBGad.LeftEdge = x;
  417.     rb->RBGad.TopEdge  = y;
  418.     rb->RBGad.Width    = width;
  419.     rb->RBGad.Height   = height;
  420.  
  421.     rb->WidgetData->left = x;
  422.     rb->WidgetData->top = y;
  423.     rb->WidgetData->width = width;
  424.     rb->WidgetData->height = height;
  425.     }
  426.  
  427. RadioButton* FOXLIB MakeRadioButton(REGA0 void *Parent, REGA1 RadioButton *MutEx, REGD0 int left, REGD1 int top, REGD2 int width,
  428.         REGD3 int height, REGD4 int fillcol, REGA2 int (* __far __stdargs callfn) (RadioButton*), REGD5 int flags, REGA3 void *extension)
  429.     {
  430.     RadioButton *rb;
  431.     struct MutexList *mlist;
  432.     GuiWindow *Wptr;
  433.     Frame *ParentFrame = NULL;
  434.  
  435.     Diagnostic("MakeRadioButton", ENTER, TRUE);
  436.     if ((MutEx && !MutEx->MList) || width < 5 || height < 5 || !Parent)
  437.         {
  438.         Diagnostic("MakeRadioButton", EXIT, FALSE);
  439.         return NULL;
  440.         }
  441.     if (!(rb = (RadioButton *) GuiMalloc(sizeof(RadioButton), 0)))
  442.         {
  443.         Diagnostic("MakeRadioButton", EXIT, FALSE);
  444.         return NULL;
  445.         }
  446.     if (!(rb->WidgetData = (Widget *) GuiMalloc(sizeof(Widget), 0)))
  447.         {
  448.         GuiFree(rb);
  449.         Diagnostic("MakeRadioButton", EXIT, FALSE);
  450.         return NULL;
  451.         }
  452.     rb->WidgetData->ObjectType = RadioButtonObject;
  453.     rb->WidgetData->Parent = Parent;
  454.     rb->WidgetData->NextWidget = NULL;
  455.     rb->WidgetData->ChildWidget = NULL;
  456.  
  457.     if (!ISGUIWINDOW(Parent))
  458.         {
  459.         ParentFrame = (Frame *) Parent;
  460.         left += ParentFrame->button.LeftEdge;
  461.         top += ParentFrame->button.TopEdge;
  462.         Wptr = (GuiWindow *) ParentFrame->button.UserData;
  463.         }
  464.     else
  465.         Wptr = (GuiWindow *) Parent;
  466.     if (ParentFrame && ParentFrame->hidden != 0)
  467.         rb->hidden = -1;
  468.     else
  469.         rb->hidden = 0;
  470.  
  471.     if (!(mlist = (struct MutexList *) GuiMalloc(sizeof(struct MutexList), 0)))
  472.         {
  473.         GuiFree(rb->WidgetData);
  474.         GuiFree(rb);
  475.         Diagnostic("MakeRadioButton", EXIT, FALSE);
  476.         return NULL;
  477.         }
  478.     if (ParentFrame && (flags & S_AUTO_SIZE) && !(ParentFrame->WidgetData->flags & S_AUTO_SIZE))
  479.         flags ^= S_AUTO_SIZE;
  480.     if (flags & S_AUTO_SIZE)
  481.         {
  482.         if (!(rb->WidgetData->os = (OriginalSize *) GuiMalloc(sizeof(OriginalSize), 0)))
  483.             {
  484.             GuiFree(mlist);
  485.             GuiFree(rb->WidgetData);
  486.             GuiFree(rb);
  487.             Diagnostic("MakeRadioButton", EXIT, FALSE);
  488.             return NULL;
  489.             }
  490.         rb->WidgetData->os->left = left;
  491.         rb->WidgetData->os->top = top;
  492.         rb->WidgetData->os->width = width;
  493.         rb->WidgetData->os->height = height;
  494.         }
  495.     else
  496.         rb->WidgetData->os = NULL;
  497.     rb->WidgetData->flags = flags;
  498.     rb->RBGad.GadgetText = NULL;
  499.  
  500.     rb->Active = TRUE;
  501.     rb->Callfn = callfn;
  502.  
  503.     // Make the bevel.  Because it's octagonal we can't use the makebevel fn.
  504.     rb->BevelPoints[1] = rb->BevelPoints[3] = rb->BevelPoints[4] = rb->BevelPoints[6] = 0;
  505.     rb->BevelPoints[2] = rb->BevelPoints[10] = 2;
  506.     rb->BevelPoints[5] = rb->BevelPoints[17] = 2;
  507.     rb->BevelPoints[8] = rb->BevelPoints[19] = 1;
  508.     rb->BLight.TopEdge = rb->BLight.LeftEdge = rb->BDark.TopEdge = rb->BDark.LeftEdge = 0;
  509.     rb->BLight.DrawMode = rb->BDark.DrawMode = JAM1;
  510.     rb->BLight.Count = rb->BDark.Count = 5;
  511.     rb->BLight.FrontPen = Gui.HiPen;
  512.     rb->BLight.BackPen = fillcol; // Ignored by Intuition - just used for storage.
  513.     rb->BLight.NextBorder = &(rb->BDark);
  514.     rb->BLight.XY = rb->BevelPoints;
  515.     rb->BDark.FrontPen = Gui.LoPen;
  516.     rb->BDark.NextBorder = NULL;
  517.     rb->BDark.XY = &(rb->BevelPoints[10]);
  518.  
  519.     memcpy(&(rb->sBLight), &(rb->BLight), sizeof(struct Border));
  520.     memcpy(&(rb->sBDark), &(rb->BDark), sizeof(struct Border));
  521.     rb->sBLight.FrontPen = Gui.LoPen;
  522.     rb->sBLight.NextBorder = &(rb->sBDark);
  523.     rb->sBDark.FrontPen = Gui.HiPen;
  524.     rb->sBDark.NextBorder = NULL;
  525.  
  526.    rb->RBGad.NextGadget   = NULL;
  527.    rb->RBGad.GadgetType   = GTYP_BOOLGADGET;
  528.    rb->RBGad.Activation   = GACT_IMMEDIATE;
  529.    rb->RBGad.Flags        = GFLG_GADGHIMAGE | (flags & BG_SELECTED ? GFLG_SELECTED : 0);
  530.    rb->RBGad.GadgetRender = (APTR) &(rb->BLight);
  531.    rb->RBGad.SelectRender = (APTR) &(rb->sBLight);
  532.    rb->RBGad.GadgetID     = 0;
  533.    rb->RBGad.UserData     = (APTR) Wptr->Win;
  534.  
  535.     mlist->Next = NULL;
  536.     mlist->Mutex = rb;
  537.     if (MutEx)
  538.         {
  539.         struct MutexList *ml = rb->MList = MutEx->MList;
  540.  
  541.         while (ml->Next)
  542.             ml = ml->Next;
  543.         ml->Next = mlist;
  544.         }
  545.     else
  546.         rb->MList = mlist;
  547.  
  548.     ResizeRadioButton(rb, left, top, width, height, FALSE);
  549.     DrawRBCentre(rb);
  550.  
  551.     rb->Next = Gui.FirstRadioButton;
  552.     Gui.FirstRadioButton = rb;
  553.  
  554.     if (rb->hidden == 0)
  555.         {
  556.        AddGadget(Wptr->Win, &(rb->RBGad), -1);
  557.        RefreshGadgets(&(rb->RBGad), Wptr->Win, NULL);
  558.         }
  559.  
  560.     Diagnostic("MakeRadioButton", EXIT, TRUE);
  561.     return rb;
  562.     }
  563.  
  564. void ResizeTickBox(TickBox *tb, int x, int y, int width, int height, BOOL eraseold)
  565.     {
  566.     /*    If the tick box is in a coloured frame then no need to blank it because the parent frame will
  567.         blank it's entire contents. */
  568.     if (eraseold && GetBackCol(tb->WidgetData->Parent) == TBWIN(tb)->RPort->BgPen)
  569.         AreaBlank(((struct Window *) tb->TickBoxGad.UserData)->RPort, tb->TickBoxGad.LeftEdge,
  570.                 tb->TickBoxGad.TopEdge, tb->TickBoxGad.Width, tb->TickBoxGad.Height);
  571.  
  572.     MakeBevel(&tb->BLight, &tb->BDark, tb->BevelPoints, 0, 0, width, height, TRUE);
  573.  
  574.     tb->TickPoints[0] = (width > 10 ? 3 : 2);
  575.     tb->TickPoints[11] = tb->TickPoints[1] = ((height - 2) / 2) + 2;
  576.     tb->TickPoints[8] = tb->TickPoints[2] = (width / 2) - 1;
  577.     tb->TickPoints[3] = height - (height > 8 ? 3 : 2);
  578.     tb->TickPoints[4] = width - (width > 10 ? 4 : 3);
  579.     tb->TickPoints[7] = tb->TickPoints[5] = (height > 8 ? 2 : 1);
  580.     tb->TickPoints[6] = tb->TickPoints[4] - 1;
  581.     tb->TickPoints[9] = tb->TickPoints[3] - 1;
  582.     tb->TickPoints[10] = tb->TickPoints[0] + 1;
  583.  
  584.    tb->TickBoxGad.LeftEdge = x;
  585.    tb->TickBoxGad.TopEdge  = y;
  586.    tb->TickBoxGad.Width    = width;
  587.    tb->TickBoxGad.Height   = height;
  588.  
  589.     tb->WidgetData->left = x;
  590.     tb->WidgetData->top = y;
  591.     tb->WidgetData->width = width;
  592.     tb->WidgetData->height = height;
  593.     }
  594.  
  595. TickBox* FOXLIB MakeTickBox(REGA0 void *Parent, REGD0 int left, REGD1 int top, REGD2 int width, REGD3 int height,
  596.         REGA1 int (* __far __stdargs callfn) (TickBox*), REGD4 int flags, REGA2 void *extension)
  597.     {
  598.     TickBox *tb;
  599.     GuiWindow *Wptr;
  600.     Frame *ParentFrame = NULL;
  601.  
  602.     Diagnostic("MakeTickBox", ENTER, TRUE);
  603.     if (!Parent)
  604.         {
  605.         Diagnostic("MakeTickBox", EXIT, FALSE);
  606.         return NULL;
  607.         }
  608.     if (!(tb = (TickBox *) GuiMalloc(sizeof(TickBox), 0)))
  609.         {
  610.         Diagnostic("MakeTickBox", EXIT, FALSE);
  611.         return NULL;
  612.         }
  613.     if (!(tb->WidgetData = (Widget *) GuiMalloc(sizeof(Widget), 0)))
  614.         {
  615.         GuiFree(tb);
  616.         Diagnostic("MakeTickBox", EXIT, FALSE);
  617.         return NULL;
  618.         }
  619.     tb->WidgetData->ObjectType = TickBoxObject;
  620.     tb->WidgetData->Parent = Parent;
  621.     tb->WidgetData->NextWidget = NULL;
  622.     tb->WidgetData->ChildWidget = NULL;
  623.  
  624.     if (!ISGUIWINDOW(Parent))
  625.         {
  626.         ParentFrame = (Frame *) Parent;
  627.         left += ParentFrame->button.LeftEdge;
  628.         top += ParentFrame->button.TopEdge;
  629.         Wptr = (GuiWindow *) ParentFrame->button.UserData;
  630.         }
  631.     else
  632.         Wptr = (GuiWindow *) Parent;
  633.     if (ParentFrame && ParentFrame->hidden != 0)
  634.         tb->hidden = -1;
  635.     else
  636.         tb->hidden = 0;
  637.  
  638.     if (ParentFrame && (flags & S_AUTO_SIZE) && !(ParentFrame->WidgetData->flags & S_AUTO_SIZE))
  639.         flags ^= S_AUTO_SIZE;
  640.     if (flags & S_AUTO_SIZE)
  641.         {
  642.         if (!(tb->WidgetData->os = (OriginalSize *) GuiMalloc(sizeof(OriginalSize), 0)))
  643.             {
  644.             GuiFree(tb->WidgetData);
  645.             GuiFree(tb);
  646.             Diagnostic("MakeTickBox", EXIT, FALSE);
  647.             return NULL;
  648.             }
  649.         tb->WidgetData->os->left = left;
  650.         tb->WidgetData->os->top = top;
  651.         tb->WidgetData->os->width = width;
  652.         tb->WidgetData->os->height = height;
  653.         }
  654.     else
  655.         tb->WidgetData->os = NULL;
  656.     tb->TickBoxGad.GadgetText = NULL;
  657.  
  658.     tb->WidgetData->flags = flags;
  659.     tb->Active = TRUE;
  660.     tb->Callfn = callfn;
  661.     tb->BLight.TopEdge = tb->BLight.LeftEdge = tb->BDark.TopEdge = tb->BDark.LeftEdge = 0;
  662.  
  663.  
  664.     /* The unselected version of the tick is just the same as the tick but in the fill pen colour so
  665.         that drawing the unselected version will remove the tick from the previously drawn selected
  666.         version.
  667.  
  668.         unselected : nstick -> light -> dark.
  669.         selected   : stick  -> light -> dark.
  670.  
  671.         This way we can re-use the light and dark borders and the only one that has to be duplicated is
  672.         the tick. */
  673.  
  674.    tb->sTick.LeftEdge    = tb->sTick.TopEdge = 0;
  675.    tb->sTick.Count       = 6;
  676.    tb->sTick.XY          = tb->TickPoints;
  677.    tb->sTick.NextBorder  = &tb->BLight;
  678.     tb->sTick.FrontPen    = Gui.TextCol;
  679.    tb->sTick.DrawMode    = JAM1;
  680.     memcpy(&tb->nsTick, &tb->sTick, sizeof(struct Border));
  681.     tb->nsTick.FrontPen = (flags & BG_CLEAR ? GetBackCol(Parent) : Gui.BackCol);
  682.  
  683.     /*    We're going to create the gadget in such a way that Intuition doesn't do anything to it when it
  684.         is clicked on - i.e. the imagery doesn't change, the state of flags doesn't change etc.  This
  685.         is so that we can cancel the user's action - i.e.  if an edit box is active and invalid and the
  686.         user clicks on the tick box it would be easy to prevent the callback function from being called
  687.         but if we made the gadget in the normal way, Intuition would still tick it or untick it for us. */
  688.    tb->TickBoxGad.NextGadget   = NULL;
  689.    tb->TickBoxGad.GadgetType   = GTYP_BOOLGADGET;
  690.    tb->TickBoxGad.Activation   = GACT_RELVERIFY;
  691.    tb->TickBoxGad.Flags        = GFLG_GADGHIMAGE;
  692.     tb->TickBoxGad.GadgetRender = (APTR) (flags & BG_SELECTED ? &tb->sTick : &tb->nsTick);
  693.     tb->TickBoxGad.SelectRender = NULL;
  694.    tb->TickBoxGad.GadgetID     = 0;
  695.    tb->TickBoxGad.UserData     = (APTR) Wptr->Win;
  696.  
  697.     tb->Ticked = flags & BG_SELECTED ? TRUE : FALSE;
  698.  
  699.     ResizeTickBox(tb, left, top, width, height, FALSE);
  700.  
  701.     tb->Next = Gui.FirstTickBox;
  702.     Gui.FirstTickBox = tb;
  703.  
  704.     if (tb->hidden == 0)
  705.         {
  706.         AddGadget(Wptr->Win, &tb->TickBoxGad, -1);
  707.         if (!(flags & BG_CLEAR))
  708.             AreaColFill(Wptr->Win->RPort, left, top, width, height, Gui.BackCol);
  709.         RefreshGadgets(&tb->TickBoxGad, Wptr->Win, NULL);
  710.         }
  711.     Diagnostic("MakeTickBox", EXIT, TRUE);
  712.     return tb;
  713.     }
  714.  
  715. void DestroyAllRadioButtons(BOOL refresh)
  716.     {
  717.     Diagnostic("DestroyAllRadioButtons", ENTER, TRUE);
  718.     while (Gui.FirstRadioButton)
  719.         DestroyRadioButton(Gui.FirstRadioButton, refresh);
  720.     Diagnostic("DestroyAllRadioButtons", EXIT, TRUE);
  721.     }
  722.  
  723. void DestroyAllTickBoxes(BOOL refresh)
  724.     {
  725.     Diagnostic("DestroyAllTickBoxes", ENTER, TRUE);
  726.     while (Gui.FirstTickBox)
  727.         DestroyTickBox(Gui.FirstTickBox, refresh);
  728.     Diagnostic("DestroyAllTickBoxes", EXIT, TRUE);
  729.     }
  730.  
  731. void DestroyWinRadioButtons(GuiWindow *gw, BOOL refresh)
  732.     {
  733.     BOOL message = FALSE;
  734.     RadioButton *rb = Gui.FirstRadioButton, *nrb = NULL;
  735.     Diagnostic("DestroyWinRadioButtons", ENTER, TRUE);
  736.     if (!gw)
  737.         {
  738.         Diagnostic("DestroyWinRadioButtons", EXIT, FALSE);
  739.         return;
  740.         }
  741.     while (rb)
  742.         {
  743.         nrb = rb->Next;
  744.         if ((struct Window *) rb->RBGad.UserData == gw->Win)
  745.             {
  746.             DestroyRadioButton(rb, refresh);
  747.             message = TRUE;
  748.             }
  749.         rb = nrb;
  750.         }
  751.     if (Gui.CleanupFlag && message)
  752.         SetLastErr("Window closed before all of its radio buttons were destroyed.");
  753.     Diagnostic("DestroyWinRadioButtons", EXIT, TRUE);
  754.     }
  755.  
  756. void DestroyWinTickBoxes(GuiWindow *gw, BOOL refresh)
  757.     {
  758.     BOOL message = FALSE;
  759.     TickBox *tb = Gui.FirstTickBox, *ntb = NULL;
  760.     Diagnostic("DestroyWinTickBoxes", ENTER, TRUE);
  761.     if (!gw)
  762.         {
  763.         Diagnostic("DestroyWinTickBoxes", EXIT, FALSE);
  764.         return;
  765.         }
  766.     while (tb)
  767.         {
  768.         ntb = tb->Next;
  769.         if ((struct Window *) tb->TickBoxGad.UserData == gw->Win)
  770.             {
  771.             DestroyTickBox(tb, refresh);
  772.             message = TRUE;
  773.             }
  774.         tb = ntb;
  775.         }
  776.     if (Gui.CleanupFlag && message)
  777.         SetLastErr("Window closed before all of its tick boxes were destroyed.");
  778.     Diagnostic("DestroyWinTickBoxes", EXIT, TRUE);
  779.     }
  780.